#ifndef COMPETENCECLASSEBASE_H
#define COMPETENCECLASSEBASE_H

#include "ADDArticleObjet.h"

#include <string>

/**
 * Permet de gérer le type de compétence.
 */
enum ScoreAdditionnel {
  Indefini = -1, /**< Utilisé pour les ensembles et compétences à
		    tiroir. */
  Aucun,         /**< Compétence "normale", pouvant être associée à un
		    pourcentage */
  Nombre,        /**< Compétence associée à un nombre dépendant du
		    niveau */
  Pourcentage    /**< Compétence associée à un pourcentage dépendant
		    du niveau */
};

/**
 * Classe qui sert de base à tout type de compétence de classe : il y
 * a celles qui ont un score à pourcentage associé (comme "Lire des
 * langues inconnues" pour un voleur), certaines qui sont associé à un
 * score qui ne dépend que du niveau, et éventuellement ajusté par la
 * valeur d'un trait (comme "Neutralisation" pour un rôdeur). Les
 * compétences toutes simple sont également implémentées bien
 * évidemment.
 *
 * Le but est de séparer ces différents type de compétences, afin de
 * simplifier l'implémenation, car l'ancienne classe CompetenceClasse
 * gérait le tout.
 *
 * @author Johan "Solo" Luisier
 */
class CompetenceClasseBase : public ADDArticleObjet
{
 public:
  CompetenceClasseBase( const std::string& nomType, const std::string& comp,
			const std::string& alias, const unsigned& prix );
  CompetenceClasseBase( const CompetenceClasseBase& compClasse );
  virtual ~CompetenceClasseBase();
  CompetenceClasseBase& operator=( const CompetenceClasseBase& lsComp );
  const std::string& aliasNom() const;
  void setAliasNom( const std::string& alias );
  const bool& aliasDefini() const;
  virtual const bool& pourcentage() const;
  virtual const unsigned& valeurBase() const;
  virtual const ScoreAdditionnel& autreScore() const = 0;
  virtual const unsigned& sousCategorie() const;
  virtual const unsigned& adresseBase() const;
  virtual const bool& sousCategorieDefinie() const;
  virtual const bool& choixExclusif() const;

  /**
   * Méthode permettant la copie profonde d'une instance héritant de
   * CompetenceClasseBase tout en renvoyant un pointeur sur une
   * CompetenceClasseBase.
   *
   * @return un pointeur sur une CompetenceClasseBase, qui est alloué
   * dynamiquement dans la méthode!
   */
  virtual CompetenceClasseBase * creerCopie() const = 0;
  
  /**
   * Permet de réaliser l'affichage simple d'une CompClasse. Le
   * nom et le coût sont affichés, et les éventuels autres attributs,
   * tels que le pourcentage de base, ou alors si elle est associée à
   * un score dépendant du niveau.
   *
   * On délègue le vrai travail à la méthode
   * CompetenceClasseBase::afficherInstance.
   *
   * @param[in] os flot de sortie sur lequel on veut écrire.
   * @param[in] lsComp capacité que l'on veut écrire.
   *
   * @return le flot os, modifié.
   */
  friend ostream& operator<<( ostream& os, const CompetenceClasseBase& lsComp );
  /**
   * Permet de réaliser l'affichage simple d'une CompClasse. Le
   * nom et le coût sont affichés, et les éventuels autres attributs,
   * tels que le pourcentage de base, ou alors si elle est associée à
   * un score dépendant du niveau.
   *
   * On délègue le vrai travail à la méthode
   * CompetenceClasseBase::afficherInstance.
   *
   * @param[in] flot instance de FlotMessage dans laquelle on veut
   * écrire.
   * @param[in] lsComp capacité que l'on veut écrire.
   *
   * @return flot, une fois modifié.
   */
  friend FlotMessage& operator<<( FlotMessage& flot,
				  const CompetenceClasseBase& lsComp );
 protected:

  /**
   * L'affichage dépend du type actuel de la classe, donc on doit
   * définir une méthode virtuelle pure qui fait le rendu dans le flot
   * désiré.
   *
   * @param[in] os flot de sortie sur lequel on veut écrire.
   */
  virtual void afficherInstance( ostream& os ) const = 0;

  /**
   * L'affichage dépend du type actuel de la classe, donc on doit
   * définir une méthode virtuelle pure qui fait le rendu dans le flot
   * désiré.
   *
   * @param[in] flot instance de FlotMessage dans laquelle on veut
   * écrire.
   */
  virtual void afficherInstance( FlotMessage& flot ) const = 0;

  std::string AliasNom; /**< Nom de la compétence, utilisé pour la
		       génération des noms de fichiers / dossiers. */
  bool AliasDefini; /**< Contient \e true si un alias a été défini. */

  /**
   * Nombre renvoyé à la place du coût, du numéro de sous-catégorie,
   * d'adresse de base, ... lorsque celui-ci n'est pas défini. La
   * valeur est zéro.
   */
  static const unsigned UnsignedNull;
  /**
   */
  static const bool BoolFalse;
  static const bool BoolTrue;
};

#endif // COMPETENCECLASSEBASE_H
